//
// Created by wangjunjun on 2024/2/19.
//

#include "configmanger.h"
#include "../log/log.h"
#include <mutex>
#include <fstream>
#include <iostream>
#include "reader.h"
std::shared_ptr<CConfigManager> CConfigManager::mInstance= nullptr;
std::once_flag CConfigManager::mflag;
CConfigManager::CConfigManager():m_strConfigPath(""){
    m_jsnConfig.clear();
}
CConfigManager::~CConfigManager(){
    m_strConfigPath.clear();
    m_jsnConfig.clear();
}
//当使用std::call_once时，需要使用std::shared_ptr的自定义删除器来释放单例实例。
//这可以通过传递一个lambda函数作为std::shared_ptr的第二个参数来实现。
/*
 * std::shared_ptr将使用自定义的删除器来释放单例实例。现在，应该能够成功编译并运行你的代码。对于高并发情况下的唯一性，
 * std::call_once将确保只有一个线程能够创建单例实例，并安全地共享该实例。
*/
std::shared_ptr<CConfigManager> CConfigManager::GetInstance() {
    std::call_once(mflag, []() {
        mInstance = std::shared_ptr<CConfigManager>(new CConfigManager(),
                                                    [](CConfigManager* ptr){delete ptr;});
    });

    return mInstance;
}
bool CConfigManager::loadConfig(const std::string &strConfigFilePath, Json::Value &jsnConfig) {
    std::ifstream ifs(strConfigFilePath, std::ifstream::binary);
    // get pointer to associated buffer object
    std::filebuf* pbuf = ifs.rdbuf();
    // get file size using buffer's members
    std::size_t size = pbuf->pubseekoff(0, ifs.end, ifs.in);
    pbuf->pubseekpos(0, ifs.in);
    // allocate memory to contain file data
    char* pBuffer = new char[size];
    if (nullptr == pBuffer)
    {
        // log
        LOG_ERROR("nullptr == pBuffer");
        return false;
    }
    // get file data
    pbuf->sgetn(pBuffer, size);
    ifs.close();
    // write content to stdout
    std::string strBuf = pBuffer;
    delete[] pBuffer;

    if (!strBuf.empty())
    {
        Json::Reader tmpReader;
        //Json::CharReader
        Json::Value tmpValue;
        if (!tmpReader.parse(strBuf, tmpValue))
        {
            LOG_ERROR("logfile :" << strConfigFilePath << " parse error");
            return false;
        }
        jsnConfig = tmpValue;
        m_jsnConfig = tmpValue;
        m_strConfigPath = strConfigFilePath;
    }
    return true;
}
bool CConfigManager::getConfig(const std::string &strConfigName, Json::Value &jsnConfig) {
    if(strConfigName.empty()){
        LOG_ERROR("strConfigName empty");
        return  false;
    }
    LOG_DEBUG("getConfig cfgname :" << strConfigName);
    if("all" == strConfigName){
        jsnConfig = m_jsnConfig;
    }if(m_jsnConfig.isMember(strConfigName)){
        jsnConfig = m_jsnConfig[strConfigName];
    }
    return true;
}
bool CConfigManager::setConfig(const std::string &strConfigName, Json::Value &jsnConfig) {
    if(strConfigName.empty()){
        LOG_ERROR("strConfigName empty()");
        return false;
    }
    if(!jsnConfig.isNull() && m_jsnConfig.isMember(strConfigName)){
        m_jsnConfig[strConfigName] = jsnConfig;
        Json::StyledWriter writer;
        std::ofstream  fout(m_strConfigPath);
        if(!fout){
            LOG_ERROR("Open file error !");
        }else {
            fout.clear();
            fout << m_jsnConfig.toStyledString() << std::endl;
            fout.close();
        }
    }
    return true;
}
